
#include					<iostream>
#include					"Speaker.h"

Speaker::Speaker()
{
	_sample_rate = 48000;
//	_sample_rate = 44100;
	_frames_per_buffer = 480;
	_num_channels = 2;
//	_buffer.init();
}

Speaker::~Speaker()
{
	if (_stream)
		Pa_CloseStream(_stream);
}

static int					playCallback( const void *inputBuffer, void *outputBuffer,
                              unsigned long framesPerBuffer,
                              const PaStreamCallbackTimeInfo* timeInfo,
                              PaStreamCallbackFlags statusFlags,
                              void *userData)
{
	Speaker			*speaker = reinterpret_cast<Speaker *>(userData);

	return speaker->playCall((short *) outputBuffer);
}

int							Speaker::playCall(short *outputBuffer)
{
	if (!_buffer.empty())
	{
		size_t to_calc = _frames_per_buffer * _num_channels;
		_mutex.lock();
		ssample	*sample = _buffer.front();
		_buffer.pop();
//		while (!_buffer.empty() && sample->ts < _buffer.front()->ts)
//		{
//			delete sample->sample;
//			delete sample;
//			sample = _buffer.front();
//			_buffer.pop();
//		}
		short	*input = sample->sample;
		_mutex.unlock();
		for (size_t i = 0; i < to_calc && !_buffer.empty(); ++i)
		{
			outputBuffer[i] = input[i];
		}
		delete input;
	}
	return _status;
}

void						Speaker::init()
{
	PaError		err;

	_outputParameters.device = Pa_GetDefaultOutputDevice(); /* default output device */
	_outputParameters.channelCount = _num_channels;                     /* stereo output */
    _outputParameters.sampleFormat =  paInt16;
	_outputParameters.suggestedLatency = Pa_GetDeviceInfo(_outputParameters.device)->defaultLowOutputLatency;
    _outputParameters.hostApiSpecificStreamInfo = NULL;

   err = Pa_OpenStream(&_stream, NULL, &_outputParameters,
		_sample_rate, _frames_per_buffer, paClipOff,
					playCallback, this);
}

void						Speaker::stop()
{
	_status = paComplete;
	Pa_StopStream(_stream);
}

void						Speaker::start()
{
	if(_stream)
	{
		_status = paContinue;
		while (!_buffer.empty())
			_buffer.pop();
		Pa_StartStream(_stream);
	}
}

void						Speaker::write(ISoundPacket* data, unsigned int stamp)
{
	_mutex.lock();
	ssample *sample = new ssample;

	sample->sample = data->data();
	sample->ts = stamp;
	_buffer.push(sample);
	_mutex.unlock();
}
